package com.tsinjie.metadata.database;

import com.tsinjie.metadata.database.model.Database;
import com.tsinjie.metadata.database.model.Table;
import com.tsinjie.metadata.exception.BuildException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Timestamp;
import java.util.List;

/**
 * Created by LiuXunming on 2015-10-29.
 * Database构建抽象父类
 */
public abstract class AbstractDatabaseBuilder<Source> implements DatabaseBuilder {
    protected Logger logger = LoggerFactory.getLogger(getClass());
    /**
     * 构建数据来源
     */
    protected Source source;

    protected AbstractDatabaseBuilder(Source source) {
        this.source = source;
    }

    /**
     * 构建对象
     *
     * @return
     */
    public Database build() {
        /**
         * 返回数据信息
         */
        Database database = null;
        logger.debug("DatabaseBuilder begin : " + new Timestamp(System.currentTimeMillis()));
        try {
            database = database();
            logger.debug("build database success.");
            tables(database);
            logger.debug("build tables success.");
            List<Table> tables = database.getTables();
            fields(tables);
            logger.debug("build fields success.");
            primaryKeys(tables);
            logger.debug("execute primaryKeys success.");
            importFields(tables);
            logger.debug("execute importFields success.");
            clearUp(tables);
            logger.debug("execute clearUp success.");
            exportFields(tables);
            logger.debug("execute exportFields success.");
        } catch (Exception e) {
            throw new BuildException(e);
        } finally {
            afterProcess();
        }
        logger.debug("DatabaseBuilder end : " + new Timestamp(System.currentTimeMillis()));
        return database;
    }


    /**
     * 构建Database对象
     * {@link com.tsinjie.metadata.database.model.Database}
     *
     * @return Database
     * @throws Exception
     */
    protected abstract Database database() throws Exception;

    /**
     * 构建表信息
     * {@link com.tsinjie.metadata.database.model.Table}
     *
     * @param database
     * @throws Exception
     */
    protected abstract void tables(Database database) throws Exception;

    /**
     * 构建字段信息
     * {@link com.tsinjie.metadata.database.model.Column}
     *
     * @param tables
     * @throws Exception
     */
    protected abstract void fields(List<Table> tables) throws Exception;

    /**
     * 构建主键信息
     * {@link com.tsinjie.metadata.database.model.Column}
     *
     * @param tables
     * @throws Exception
     */
    protected abstract void primaryKeys(List<Table> tables) throws Exception;

    /**
     * 构建外键信息
     * {@link com.tsinjie.metadata.database.model.Column}
     *
     * @param tables
     * @throws Exception
     */
    protected abstract void importFields(List<Table> tables) throws Exception;

    /**
     * 避免某字段同时为主键和外键，不在生成主外键的循环中做移除操作
     * 清理表字段（主键和外键）
     *
     * @param tables
     * @throws Exception
     */
    protected abstract void clearUp(List<Table> tables) throws Exception;

    /**
     * 构建被引用（Export）键信息
     * {@link com.tsinjie.metadata.database.model.Column}
     *
     * @param tables
     * @throws Exception
     */
    protected abstract void exportFields(List<Table> tables) throws Exception;

    /**
     * 构建完成后
     */
    protected void afterProcess() {

    }
}
